import { isNumber } from "@/shared";
import type { InternalRuleItem } from "async-validator";
/* 简单校验手机号 */
function isPhone(phone: string): boolean {
  if (phone === "" || phone === null || phone === undefined) return false;
  return /^1(3\d|4\d|5\d|6\d|7\d|8\d|9\d)\d{8}$/g.test(phone);
}

/* 自定义校验手机号 */
function mobildVerify(_rule: InternalRuleItem, value: string, callback: (error?: Error) => void): void {
  if (value === "") {
    callback(new Error("请填写手机号"));
  } else if (!isPhone(value)) {
    callback(new Error("请填写正确的手机号"));
  } else {
    callback();
  }
}

/* 自定义校验密码 */
function useSamePasswordVerify(_rule: InternalRuleItem, value: string, callback: (error?: Error) => void, new_password: string): void {
  if (value === "") {
    callback(new Error("确认密码必填"));
  } else if (value !== new_password) {
    callback(new Error("两次密码输入不一致"));
  } else {
    callback();
  }
}

/* 自定义校验时间 */
function timeVerify(_rule: InternalRuleItem, value: string | number, callback: (error?: Error) => void, desc = "请选择时间") {
  if (value === "" || value == 0) {
    callback(new Error(desc));
  } else {
    callback();
  }
}
function commissionRateVerify(_rule: InternalRuleItem, value: string | number, callback: (error?: Error) => void) {
  if (value === "") {
    callback(new Error("请填写分佣率"));
  } else if (!isNumber(value)) {
    callback(new Error("请填写数字"));
  } else if ((value as number) < 100) {
    callback(new Error("分佣率需大于100"));
  } else if ((value as number) > 2900) {
    callback(new Error("分佣率需小于2900"));
  } else {
    callback();
  }
}

/**
 * @param {Array} idList 要删除的id列表
 * @param {Array} list 在哪个列表删除
 * @param {String} id 以哪个字段进行删除
 * 删除选中的数据
 */
function handleSelectDeleteData<T extends Record<K, string | number>, K extends keyof T>(idList: Array<string | number>, list: Array<T>, id: K = "id" as K) {
  list = list.filter((item: T) => !idList.includes(item[id] as string | number));
}

/* 获取年月日 时分秒 yyyy-MM-dd hh:mm:ss*/
function dateFormatYMDHMS(timestamp: number): string {
  const date = new Date(timestamp);
  const Y = date.getFullYear() + "-";
  const M = (date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1) + "-";
  const D = (date.getDate() < 10 ? "0" + date.getDate() : date.getDate()) + " ";
  const h = (date.getHours() < 10 ? "0" + date.getHours() : date.getHours()) + ":";
  const m = (date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes()) + ":";
  const s = (date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds()) + "";
  return Y + M + D + h + m + s;
}
/* 获取 时分秒 hh:mm:ss*/
function dateFormatHMS(timestamp: number): string {
  const date = new Date(timestamp);
  const h = (date.getHours() < 10 ? "0" + date.getHours() : date.getHours()) + ":";
  const m = (date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes()) + ":";
  const s = (date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds()) + "";
  return h + m + s;
}

/* 获取年月日 yyyy-MM-dd*/
function dateFormatYMD(timestamp: number): string {
  const date = new Date(timestamp);
  const Y = date.getFullYear() + "-";
  const M = (date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1) + "-";
  const D = (date.getDate() < 10 ? "0" + date.getDate() : date.getDate()) + " ";
  return Y + M + D;
}

/* 校验并返回格式化后的时间 yyyy-MM-dd hh:mm:ss */
function handleVerifyFormatDate(timestamp: number): string {
  if (["", null, 0, "0"].includes(timestamp)) return "--";
  return dateFormatYMDHMS(Number(timestamp) * 1000);
}
/* 校验并返回格式化后的时间：年月日 */
function handleVerifyFormatYMDDate(timestamp: number): string {
  if (["", null, 0, "0"].includes(timestamp)) return "--";
  return dateFormatYMD(Number(timestamp) * 1000);
}
/* 校验并返回格式化后的时间：hh:mm:ss */
function handleVerifyFormatHMSDate(timestamp: number): string {
  if (["", null, 0, "0"].includes(timestamp)) return "--";
  return dateFormatHMS(Number(timestamp) * 1000);
}
/* 格林尼治时间转date */
function renderTime(date: Date | string): string {
  if (date === "") {
    return "";
  } else {
    const _date = new Date(date).toJSON();
    return new Date(+new Date(_date) + 8 * 3600 * 1000)
      .toISOString()
      .replace(/T/g, " ")
      .replace(/\.[\d]{3}Z/, "");
  }
}

/**
 * 获取今天某点时间
 */
function anyDate(hours: number, minutes = 0) {
  return new Date(new Date(new Date().getTime()).setHours(hours, minutes, 0));
}
/* 导出excel信息 */
function exportExcel(data: Blob, _name: string) {
  const blob = new Blob([data], {
    type: "application/vnd.ms-excel"
  });
  const fileName = _name;
  const elink = document.createElement("a");
  elink.download = fileName;
  elink.style.display = "none";
  /* 将blob对象转成url地址 */
  elink.href = URL.createObjectURL(blob);
  document.body.appendChild(elink);
  elink.click();
  URL.revokeObjectURL(elink.href); // 释放URL 对象
  document.body.removeChild(elink);
}

/**
 * 防抖函数
 *
 * @param   {function}  fn      需要防抖的函数
 * @param   {number}  duration  间隔时间
 *
 * @return  {function}          返回防抖函数
 */
function debounce<F extends (...args: unknown[]) => void>(fn: F, duration: number): (this: ThisParameterType<F>, ...args: Parameters<F>) => void {
  let timeout: ReturnType<typeof setTimeout> | null = null;

  return function (this: ThisParameterType<F>, ...args: Parameters<F>) {
    if (timeout !== null) {
      clearTimeout(timeout);
    }
    timeout = setTimeout(() => {
      fn.apply(this, args);
    }, duration);
  };
}

/* @param   {String}  input  需要处理的字符串 转数组 */
function splitAndFilter(input: string) {
  if (!input) return [];
  return input.split(",").filter(item => item.trim() !== "");
}

/**
 * 将异步函数包装成一个更安全的异步函数
 * 此装饰器函数捕获异步函数执行时可能抛出的错误，使错误处理更加集中和统一
 * 特别适用于Promise-based的异步编程，提高代码的健壮性
 *
 * @param {Function} asyncFunc - 需要包装的异步函数
 * 该函数应该返回一个Promise对象
 * @returns {Function} 包装后的异步函数，返回一个包含错误对象和结果的数组
 */
// function safeAsync(asyncFunc: Function) {
//   return async function (...args) {
//     try {
//       const result = await asyncFunc(...args);
//       return [null, result]; // 返回一个数组，第一个元素为null表示没有错误，第二个元素为结果
//     } catch (err) {
//       return [err, null]; // 返回一个数组，第一个元素为错误对象，第二个元素为null
//     }
//   };
// }
function safeAsync<Return, Args extends unknown[]>(asyncFunc: (...args: Args) => Promise<Return>): (...args: Args) => Promise<[Error | null, Return | null]> {
  return async function (...args: Args): Promise<[Error | null, Return | null]> {
    try {
      const result = await asyncFunc(...args);
      return [null, result]; // 返回一个数组，第一个元素为null表示没有错误，第二个元素为结果
    } catch (err) {
      return [err instanceof Error ? err : new Error(String(err)), null]; // 确保错误是Error类型
    }
  };
}

/**
 * 截取姓名，返回姓和名
 *
 * @param   {String}  fullName  完整的姓名
 *
 * @return  {Object}  返回姓和名的对象
 */
function handleExtractSurnameAndName(fullName: string) {
  // 假设第一个字是姓氏，剩下的部分是名字
  const firstName = fullName && fullName.charAt(0);
  const lastName = fullName && fullName.slice(1);
  return {
    firstName,
    lastName
  };
}

/*
 * @param   {String}  phoneNumber  完整的手机号
 *
 * @return  {Object}  返回截取后的手机号
 */
function handleExtractFirstNineAndLastTwoDigits(phoneNumber: string) {
  const firstPhone = phoneNumber.slice(0, 9);
  const lastPhone = phoneNumber.slice(-2);
  return {
    firstPhone,
    lastPhone
  };
}

export {
  isPhone,
  mobildVerify,
  useSamePasswordVerify,
  timeVerify,
  handleSelectDeleteData,
  dateFormatYMDHMS,
  handleVerifyFormatDate,
  renderTime,
  anyDate,
  dateFormatHMS,
  handleVerifyFormatHMSDate,
  handleVerifyFormatYMDDate,
  exportExcel,
  debounce,
  splitAndFilter,
  safeAsync,
  commissionRateVerify,
  handleExtractSurnameAndName,
  handleExtractFirstNineAndLastTwoDigits
};
